package com.bac.rentmap.ad.flat.crawler.realtby;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;

import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

import com.bac.rentmap.ad.crawler.Context;
import com.bac.rentmap.ad.crawler.phone.PhoneNormalizer;
import com.bac.rentmap.ad.crawler.stepped.AbstractSteppedAdCrawler;
import com.bac.rentmap.ad.flat.Constants;
import com.bac.rentmap.ad.flat.crawler.FlatCrawledAd;
import com.bac.rentmap.ad.flat.crawler.ParsingHelper;

/**
 * Crawls data from realt.by step by step. Records per page: 100. City: Minsk.
 * Rent type: long. Ordering: date descending. Used page: for print.
 *
 * @author Andrew Osipenko
 */
public class RealtBySteppedAdCrawler extends
        AbstractSteppedAdCrawler<FlatCrawledAd> {
    private static final Logger log = Logger
            .getLogger(RealtBySteppedAdCrawler.class.getName());
    private ParsingHelper parsingHelper;
    private PhoneNormalizer phoneNormalizer;

    // TODO: remove, use page form {@link Context}
    private int page;
    private String city = "minsk";

    public RealtBySteppedAdCrawler(Context context) {
        if (context.getPage() != null) {
            page = context.getPage() + 1;
        } else {
            page = 1;
        }
    }

    protected String getNextUrl() {
        String res = "http://realt.by/rent/flat-for-long/show/table/page/"
                + page++
                + "/print.html?tx_uedbflatrent_pi2%5Brec_per_page%5D=100&tx_uedbflatrent_pi2%5BDATA%5D%5Btown_id%5D%5Be%5D=5102&tx_uedbflatrent_pi2%5BDATA%5D%5Btown_name%5D%5Blike%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bstreet_name%5D%5Blike%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Brooms%5D%5Be%5D%5B1%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Brooms%5D%5Be%5D%5B2%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bstoreys%5D%5Bge%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bstoreys%5D%5Ble%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bstorey%5D%5Bge%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bstorey%5D%5Ble%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bterm_of_lease%5D%5Be%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bprepayment%5D%5Be%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bterms%5D%5Be%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bprice%5D%5Bge%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bprice%5D%5Ble%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bx_days_old%5D%5Ble%5D=&tx_uedbflatrent_pi2%5BDATA%5D%5Bagency_id%5D%5Be%5D=&tx_uedbflatrent_pi2%5Bsort_by%5D%5B0%5D=date_revision&tx_uedbflatrent_pi2%5Bsort_by%5D%5B1%5D=&tx_uedbflatrent_pi2%5Basc_desc%5D%5B0%5D=1&tx_uedbflatrent_pi2%5Basc_desc%5D%5B1%5D=0&submit=%CD%E0%F7%E0%F2%FC%20%EF%EE%E8%F1%EA";
        log.info("Requesting URL " + res);
        return res;
    }

    protected FlatCrawledAd parseCrawledAd(TagNode tagNode)
            throws XPatherException {
        FlatCrawledAd res = new FlatCrawledAd();
        String address = getValue(tagNode, "/td[4]/text()");
        parsingHelper.parseStreetAndBuilding(address, res);
        String priceString = getValue(tagNode, "/td[12]/text()");
        log.info("Price " + priceString);
        if (priceString != null)
            res.setPrice(Integer.valueOf(priceString));
        String phone = parsePhone(tagNode, "/td[14]");
        res.setPhone(phoneNormalizer.normalizePhone(phone));
        res.setDescription(getValue(tagNode, "/td[15]/text()"));
        res.setPublishingDate(parsePublishingDate(tagNode, "/td[16]/text()",
                "dd-MM-yy"));
        res.setRoom(parseRoom(getValue(tagNode, "/td[2]/text()")));
        res.setCity(city);
        res.setSourceUrl("http://realty.by");
        res.setReadyForTransformation(true);
        return res;
    }

    private String parseRoom(String room) {
        if (room.contains("к")) {
            return Constants.ROOM_MARKER;
        } else {
            return room.substring(0, room.indexOf("/"));
        }
    }

    private Date parsePublishingDate(TagNode tagNode, String xpath,
            String pattern) throws XPatherException {
        String dateString = convertHtml2text((CharSequence) evaluateXPath(
                tagNode, xpath));

        if (dateString == null) {
            log.warning("Publishing date is empty for " + tagNode);
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        try {
            log.info("Parsing " + dateString);
            return format.parse(dateString);
        } catch (ParseException e) {
            log.warning("Can't parse publishing date from " + dateString);
            return null;
        }
    }

    private String parsePhone(TagNode tagNode, String xpath)
            throws XPatherException {
        TagNode phoneNode = (TagNode) evaluateXPath(tagNode, xpath);
        String res = "";
        try {
            String prefix = convertHtml2text((String) evaluateXPath(phoneNode,
                    "strong/img/@alt"));
            if (prefix != null)
                res += parsingHelper.parsePhone(prefix);
        } catch (IllegalArgumentException e) {
        }
        res += convertHtml2text(phoneNode.getText().toString());
        return parsingHelper.cleanPhone(res);
    }

    @Override
    protected String getItemXPath() {
        return "//body/div/table/tbody/tr[position() > 3]";
        // .evaluateXPath("//body/div/table/tbody/tr[count(td) = 1]");
    }

    public void setParsingHelper(ParsingHelper parsingHelper) {
        this.parsingHelper = parsingHelper;
    }

    public void setPhoneNormalizer(PhoneNormalizer phoneNormalizer) {
        this.phoneNormalizer = phoneNormalizer;
    }
}
